import tkinter as tk
from tkinter import messagebox,ttk
import sys
import random
import os
import ctypes

try:
    from net_weather import Weather,city_json
except FileNotFoundError:  #找不到城市代码json文件
    root = tk.Tk()
    root.withdraw()
    messagebox.showerror('Weather','我们找不到存储城市信息的文件了…'
                         '请向提供给您本程序的人寻求帮助')
    sys.exit()

ICON_FILE = 'weather_icon/'
HOME_FILE = 'home.txt'
SOURCE_FILE = 'tk_source/'

class MainAPP(object):
    main_bg = ('#ff9ff3','#0cf8fe','#fff988','#78fe78')
    
    def __init__(self):
        self.root = tk.Tk()

        # 适配高dpi
        #ctypes.windll.shcore.SetProcessDpiAwareness(1)
        #ScaleFactor = ctypes.windll.shcore.GetScaleFactorForDevice(0)
        # 由缩放率计算出dpi并调用tk的缩放函数
        # 每1%的缩放率对应1/72的dpi。也就是说，正常100%缩放率屏幕的dpi为72
        #self.root.tk.call('tk', 'scaling', ScaleFactor / 72)
        
        self.root.title('Weather')

        self.main_bg = random.choice(self.main_bg)  #抽取一个颜色作为本次主题色

        self.entrance()

    def entrance(self):
        '''Display the entrance "cartoon"'''
        self.image = tk.PhotoImage(file=SOURCE_FILE+'background.png')
        self.image1 = tk.PhotoImage(file=SOURCE_FILE+'label1.png')
        self.search_image = tk.PhotoImage(file=SOURCE_FILE+'search_1.png')
        self.home_image = tk.PhotoImage(file=SOURCE_FILE+'home_1.png')
        self.set_image = tk.PhotoImage(file=SOURCE_FILE+'setting.png')
       
        self.welcome = tk.Frame(self.root)
        canvas = tk.Canvas(self.welcome)
        canvas.create_image(100,200,image=self.image)
        
        l1 = tk.Label(self.welcome,text='Weather',font=('Cooper Black',40)
                 ,fg='#ff15e2',compound='center',bd=0,image=self.image1)
        l2 = tk.Label(self.welcome,text='-Simple perfect',font=('Cambria',10)
                 ,fg='#9886ff',compound='center')
        canvas.create_window(190,100,window=l1)
        canvas.create_window(190,200,window=l2)
        
        canvas.pack(fill=tk.BOTH)
        self.welcome.pack()
        wait_time = 2500 if not os.path.exists(HOME_FILE) else 1000
        self.root.after(wait_time,self.mainscreen)
        
        city_json.load_json()  #把加载json文件“耗时”的工作放在欢迎界面加载
        self.load_icon()  #加载天气图标
        self.assign_theme()  #注册主题

    def mainscreen(self):
        '''展示主界面'''
        if self.welcome:
            self.welcome.destroy()
##        self.display_menu()

        self.root['background'] = self.main_bg  

        left_menu = ttk.Frame(self.root,style='Left.TFrame')
        home = ttk.Label(left_menu,image=self.home_image)
        home.bind('<Button-1>',lambda event:self.switch_frame('main'))
        home.pack()
        setting = ttk.Label(left_menu,image=self.set_image)
        setting.bind('<Button-1>',lambda event:self.switch_frame('setting'))
        setting.pack()
        left_menu.pack(side='left',fill=tk.Y)

        top_menu = ttk.Frame(self.root,style='Top.TFrame')
        top_menu.pack(side='top',fill=tk.X)
        search_button = ttk.Label(top_menu,image=self.search_image,
                                  style='Button_off.TLabel')
        search_button.pack(side='right')
        search_button.bind('<Button-1>',
                           lambda event:self.search_button_command(event,search_button))
        search_button.bind('<ButtonRelease-1>',
                           lambda event:search_button.configure(style='Button_off.TLabel'))

        self.cho = ttk.Combobox(top_menu,style='My.TCombobox',
                                postcommand=self.combobox_post_command)
        self.cho.bind('<<ComboboxSelected>>',lambda event:self.load_data(self.cho.get()))
        self.cho.bind('<Return>',lambda event:self.load_data(self.cho.get()))
        self.hide_cho = True

        main_frame = ttk.Frame(self.root,style='My.TFrame')
        
        self.city_name_label = ttk.Label(main_frame,style='Title.TLabel')
        self.city_name_label.pack(pady=15)

        weather_frame = ttk.Frame(main_frame,style='My.TFrame')
        self.icon = ttk.Label(weather_frame,style='Info.TLabel')
        self.icon.pack(side='left')
        self.temp = ttk.Label(weather_frame,style='Info.TLabel')
        self.temp.pack(side='right',padx=10)
        weather_frame.pack()

        self.type = ttk.Label(main_frame,style='Title.TLabel')
        self.type.pack()
        self.update_time = ttk.Label(main_frame,style='Msg.TLabel')
        self.update_time.pack()

        other_frame = ttk.Frame(main_frame,style='My.TFrame')
        ttk.Label(other_frame,style='Info_small.TLabel',text='空气质量指数  ').pack(side='left')
        self.aqi = tk.Label(other_frame)
        self.aqi.pack(side='left')
        self.other_data = ttk.Label(other_frame,style='Info_small.TLabel')
        self.other_data.pack(side='left',padx=2)
        other_frame.pack()

        ttk.Label(main_frame,text='15天天气预报',style='Info_small.TLabel').pack()
        self.canvas = tk.Canvas(main_frame,bg=self.main_bg,bd=0,relief='flat'
                                ,scrollregion=(-600,0,750,300))
        canvas_frame = ttk.Frame(self.canvas,style='My.TFrame')
        
        self.days = [ttk.Frame(canvas_frame,style='My.TFrame') for _ in range(14)]
        self.day = [ttk.Label(frame,style='Info_small.TLabel') for frame in self.days]
        self.date = [ttk.Label(frame,style='Info_small.TLabel') for frame in self.days]

        for one in self.date:  #日期提示Label
            one.pack()
        for one in self.day:  #高低温
            one.pack(side='left',pady=5)
        for one in self.days:
            one.pack(side='left')

        self.canvas.create_window(75,140,window=canvas_frame)
        self.canvas.pack(fill=tk.BOTH)

        scroll = tk.Scrollbar(main_frame,orient=tk.HORIZONTAL)
        scroll.config(command=self.canvas.xview)
        scroll.pack(fill=tk.X)

        self.canvas.config(xscrollcommand=scroll.set)
        
        city = self.get_option()
        if city:
            self.load_data(city)
            
        #以下为设置界面的创建（但不显示）
        set_frame = ttk.Frame(self.root,style='My.TFrame')
        ttk.Label(set_frame,text='启动城市设置：',style='Set_title.TLabel').pack()
        self.cho_box = ttk.Combobox(set_frame,style='My.TCombobox',values=city,
                               postcommand=self.cho_combobox_post_command)
        self.cho_box.pack(padx=15,pady=10)
        self.cho_box.bind('<<ComboboxSelected>>',lambda event:self.save_option(self.cho_box.get()))
            
        self.frames = {'main':main_frame,'setting':set_frame}
        self.switch_frame('main')

##    def display_menu(self):
##        '''生成菜单(在显示欢迎界面后)'''
##        main_menu = tk.Menu(self.root)
##        self.city_menu = tk.Menu(main_menu,tearoff=False)
##        
##        main_menu.add_cascade(label='收藏夹',menu=self.city_menu)
##        self.root.config(menu=main_menu)

    def assign_theme(self):
        '''集中注册所需的ttk样式'''
        s = ttk.Style()
        s.configure('My.TCombobox',foreground= '#363a37',
                                    selectbackground='#484dff',
                                    fieldbackground='#949494')
        s.configure('Title.TLabel',background=self.main_bg,font=('黑体',25))
        s.configure('Info_small.TLabel',background=self.main_bg,font=('楷体',12))
        s.configure('Info.TLabel',background=self.main_bg,font=('宋体',20))
        s.configure('Button_off.TLabel',relief='groove')
        s.configure('Button_on.TLabel',relief='ridge')
##        s.configure('Button_pass.TLabel',background='#999999')
        s.configure('Set_title.TLabel',background=self.main_bg,font=('黑体',15,'bold'))
        s.configure('Msg.TLabel',background=self.main_bg,font=('楷体',10))
        s.configure('Left.TFrame',background='#e0e0e0')
        s.configure('Top.TFrame',background='#c5c5c5',relief='groove')
        s.configure('My.TFrame',background=self.main_bg)

    def switch_frame(self,chosen):
        '''为左侧切换页面使用'''
        for one in self.frames.values():
            one.pack_forget()
            
        self.frames[chosen].pack(expand=True,anchor='se',fill=tk.BOTH)
        
    def load_data(self,city_name):
        '''加载城市的天气预报'''
        city_code = city_json.name_code(city_name)
        if not city_code or len(city_code) != 1:return

        weather = Weather(city_name)
        
        self.city_name_label.configure(text=weather.get_data('cityInfo')['parent']
                                       +weather.get_data('cityInfo')['city'])

        today_weather_type = weather.forecast(0)['type']
        today_weather_data = weather.get_data('data')['wendu']
        today_weather_quality = weather.get_data('data')['quality']
        
        self.icon.configure(image=random.choice(self.weather_icon[today_weather_type[0]]))
        self.temp.configure(text=today_weather_data+"℃")
        self.type.configure(text=today_weather_type)
        self.update_time.configure(text='最后更新时间'+weather.get_data('cityInfo')['updateTime'])
        self.aqi.configure(text=weather.forecast(0)['aqi'],
                           bg='green' if today_weather_quality == '优'else 'yellow' if today_weather_quality == '良' else 'red')
        self.other_data.configure(text='  风向  '+weather.forecast(0)['fx']+'   风力  '+weather.forecast(0)['fl'])

        for index,one in enumerate(self.day):
            one.config(text=weather.forecast(index+1)['high'].strip('高温')+'  '
                       +weather.forecast(index+1)['low'].strip('低温'))
        for index,one in enumerate(self.date):
            one.config(text=weather.forecast(index+1)['ymd']+'\n'
                       +weather.forecast(index+1)['week'])

    def load_icon(self):
        self.weather_icon = {}
        for _,_,file in os.walk(ICON_FILE):
            for one_file in file:
                if one_file == 'weather_icon.png' or not one_file.startswith('1_'):continue
                group = one_file.lstrip('1_')[0]
                image = tk.PhotoImage(file=ICON_FILE+one_file)
                try:
                    self.weather_icon[group].append(image)
                except KeyError:
                    self.weather_icon[group] = [image]

    def save_option(self,city):
        '''存储设置中设定的启动城市'''
        if not city_json.name_code(city):return  #查询不到城市编码则不储存
        with open(HOME_FILE,'w',encoding='utf-8') as f:
            f.write(city)

    def get_option(self):
        '''读取设置中设定的启动城市'''
        if not os.path.isfile(HOME_FILE):
            return ''
        with open(HOME_FILE,'r',encoding='utf-8') as f:
            city = f.readline().strip()  #一共只有一行

        if not city_json.name_code(city):return ''
        else:
            return city

    def cho_combobox_post_command(self):
        in_put = self.cho_box.get()
        if not in_put:
            self.cho_box['values'] = []
        else:
            self.cho_box['values'] = list(city_json.name_code(in_put,True).keys())

    def combobox_post_command(self):
        in_put = self.cho.get()
        if not in_put:
            self.cho['values'] = []
        else:
            self.cho['values'] = list(city_json.name_code(in_put,True).keys())

    def search_button_command(self,event,search_button):
        if self.hide_cho:
            self.cho.pack(side='right')
            self.hide_cho = False
        else:
            if self.cho.get():
                try:
                    self.load_data(self.cho.get())
                except ValueError as e:
                    # 底层库查询不到城市
                    messagebox.showerror('错误', str(e))
            else:
                self.cho.pack_forget()
                self.hide_cho = True
        search_button.configure(style='Button_on.TLabel')
    
    def start(self):
        self.root.mainloop()
        

if __name__ == '__main__':
    MainAPP().start()
